// Tools.h
// Created by Limou on 24-8-13.
// 公共工具

#ifndef FRONTEND_TOOLS_HPP
#define FRONTEND_TOOLS_HPP

#include <memory>
#include <thread>
#include <chrono>
#include <QDebug>
#include <QString>
#include <QFile>
#include <QTextStream>
#include <QIcon>
#include <QPixmap>
#include <QUuid>
#include <QDateTime>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>

// TODO: 工具类可以细分一下...日志类可以现代化设计一下...

// >>> class Logs begin: 日志工具类
namespace chat_system::common {
    class Logs {

    };
} // namespace chat_system::common end
// <<< class Logs end <<<

// >>> class Files Begin: 文件工具类
namespace chat_system::common {
    class Files {
        // 加载并且返回 QSS 文件中的样式字符
        static QString loadStyleSheet(const QString &filePath) {
            QFile file(filePath);
            if (file.open(QFile::ReadOnly)) {
                QTextStream stream(&file);
                QString styleSheet = stream.readAll();
                file.close();
                return styleSheet;
            } else {
                qDebug() << "Failed to open QSS file:" << filePath;
                return QString("");
            }
        }
    };
} // namespace chat_system::common end

// >>> class Tools begin: 工具类 >>>
namespace chat_system::common {
#define TEST 1 // 临时测试宏 // TODO: 这个宏不要使用了...

#define TODO(message) \
    do { \
        qDebug() << QString("%1 %2 TODO: %3").arg(__FILE__).arg(__LINE__).arg(message); \
} while(0)

    class Tools {
    private:
        inline static Tools* instance_ = nullptr; // 单例指针
        const char* loggerName_; // 日志类型
        std::shared_ptr<spdlog::logger> logger_; // 日志对象

    public:
        // 获取 Tools 实例的静态方法
        static Tools* getInstance() {
            if (instance_ == nullptr) {
                instance_ = new Tools();
            }
            return instance_;
        }

        // 设置 logger 对象
        void setLogger(const char* loggerName) {
            loggerName_ = loggerName;
        }

        // 获取 logger 对象
        std::shared_ptr<spdlog::logger> getLogger() const {
            return logger_;
        }

        // 读出文件
        bool fileToByteArray(const QString& fromPath, QByteArray& toContent)  {
            QFile file(fromPath);
            if (!file.open(QIODevice::ReadOnly) ) {
                toContent = "";
                Tools::getInstance()->getLogger()->warn("fileToByteArray() 打开文件失败");
                return false;
            } else {
                toContent = file.readAll();
                file.close(); // NOTE: 其实不写也是可以的, 出了生命周期可以自动关闭
                return true;
            }
        }

        // 写入文件
        bool byteArrayToFile(const QByteArray& fromContent, const QString& toPath)  {
            QFile file(toPath);
            if (!file.open(QIODevice::WriteOnly)) {
                Tools::getInstance()->getLogger()->warn("byteArrayToFile() 打开文件失败");
                return false;
            } else {
                file.write(fromContent);
                file.flush(); // NOTE: 必须刷新不然可能无法刷到 fromContent 中
                file.close(); // NOTE: 其实不写也是可以的, 出了生命周期可以自动关闭
                return true;
            }
        }

        // 把二进制数据转化为图片
        QIcon byteArrayToIcon(const QByteArray& byteArray) {
            QPixmap pixmap;
            pixmap.loadFromData(byteArray);
            return QIcon(pixmap);
        }

        // 获取带有标记的 uuid
        QString getUuid(const QString& flag) {
            return flag + "_" + QUuid::createUuid().toString().sliced(25, 12); // NOTE: 从原始 UUID 字符串的第 25 个字符开始截取长度为 12 的子串
        }

        // 获取当前时间戳
        int64_t getTimestamp() {
            return QDateTime::currentSecsSinceEpoch(); // 秒级时间
        }

        // 格式化时间错
        QString makeFormatTime(const int64_t& timestamp = Tools::getInstance()->getTimestamp()) {
            return QDateTime::fromMSecsSinceEpoch(timestamp * 1000).toString("MM-dd hh:mm:ss");
        }

    private:
        // 私有构造方法
        Tools() : loggerName_("console") {
            // 初始化日志对象
            logger_ = spdlog::stdout_color_mt(loggerName_);

            // 设置日志等级为最低，即 trace
            logger_->set_level(spdlog::level::trace);

            // 设置日志格式，包含时间戳、日志等级、文件名和行号
            logger_->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
            // %Y-%m-%d %H:%M:%S.%e  -> 时间戳，精确到微秒
            // %^%l%$                 -> 日志等级（带颜色）
            // %v                     -> 日志消息内容
        }

        // 私有析构方法
        ~Tools() = default; // TODO: 自动 GC 也可以考虑设置一下

        // 禁用拷贝构造方法
        Tools(Tools& other) = delete;

        // 禁用赋值拷贝方法
        Tools& operator=(Tools& other) = delete;
    };
} // namespace chat_system::common end
// <<< class Tools end <<<

#endif // FRONTEND_TOOLS_HPP
